import imaplib
import email
from email.header import decode_header
import re
from datetime import datetime, timedelta
from utils import Info
from models import ConfigurationModel
from exts import db
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


def fetch_daily_reports(since_date, end_date):  # 传入的日期为字符串
    status, info = get_config(id=1)
    if not status:
        return False, Info("未配置邮箱源")
    email_user = info.data["configEmail"]
    password = info.data["configSecretKey"]
    try:
        # 创建 IMAP 服务器连接
        if email_user.endswith('@qq.com'):
            mail = imaplib.IMAP4_SSL('imap.qq.com', 993)
        elif email_user.endswith('@163.com'):
            mail = imaplib.IMAP4_SSL('imap.163.com', 993)
        elif email_user.endswith('@sia.cn'):
            mail = imaplib.IMAP4_SSL('mail.cstnet.cn', 993)
        else:
            print("不支持的邮箱类型，请检查邮箱地址")
            return False, Info("不支持的邮箱类型，请检查邮箱地址")

        # 登录
        mail.login(email_user, password)
    except Exception as e:
        print("源邮箱登录失败, 请检查配置邮箱和密钥")
        return False, Info("源邮箱登录失败, 请检查配置邮箱和密钥")

    # 选择邮箱（INBOX 是收件箱）
    mail.select('inbox')

    # 设置搜索条件
    print(f'检索{since_date}至现在的邮件')

    # 程序这里有个bug导致不检索end_date这天，只能手动添加一天来尝试实现
    # 将 end_date 字符串转换为 datetime 对象
    end_date_obj = datetime.strptime(end_date, '%d-%b-%Y')  # 根据实际日期格式解析
    # 增加两天天，即虽然爬取昨日日报，但是今日凌晨可能或今日可能补交日报一并爬取
    end_date_obj += timedelta(days=2)
    # 将增加两天后的日期转换回字符串，为了适应 IMAP 的搜索格式
    end_date = end_date_obj.strftime('%d-%b-%Y')  # 保持原格式

    search_criteria = f'SINCE "{since_date}" BEFORE "{end_date}"'
    status, messages = mail.search(None, search_criteria)

    # 将邮件 ID 列表转换为列表
    mail_ids = messages[0].split()

    print(f'总邮件数: {len(mail_ids)}')

    reports = []  # 用于存储提取的日报信息

    # 遍历邮件
    for i in range(len(mail_ids)):
        # 获取邮件
        # status, msg_data = mail.fetch(mail_ids[i], '(RFC822)')  # 从邮件中获取邮箱的全部数据
        status, msg_data = mail.fetch(mail_ids[i], '(BODY.PEEK[])')  # 从邮件中获取邮箱而不改变状态

        # msg_data 是一个列表，包含邮件内容
        msg = email.message_from_bytes(msg_data[0][1])  # 对数据进行一个解码过程,参考太阳照常升起233

        # 解码邮件主题
        subject, encoding = decode_header(msg['Subject'])[0]
        if isinstance(subject, bytes):
            subject = subject.decode(encoding if encoding else 'utf-8')

        # print(f'邮件主题: {subject}')
        # 使用正则表达式查找主题中的姓名和日期
        match = re.search(r'【[^】]*】\s*【([^】]*)】\s*【(\d{4}\.\d{1,2}\.\d{1,2})】', subject)
        if match:
            name = match.group(1)  # 姓名
            date_str = match.group(2)  # 日期

            # 处理日期格式
            try:
                # 尝试解析日期，支持两种格式：2024.11.15 和 2024-1-1
                if '.' in date_str:
                    date_obj = datetime.strptime(date_str, '%Y.%m.%d')
                else:
                    date_obj = datetime.strptime(date_str, '%Y-%m-%d')

                # 转换为标准格式 YYYY-MM-DD
                standard_date = date_obj.strftime('%Y-%m-%d')
            except ValueError as e:
                print(f"日期格式错误: {date_str}, 错误信息: {e}")
                standard_date = None  # 如果解析失败，可以选择设置为 None 或其他默认值

            if standard_date:
                reports.append({"name": name, "date": standard_date})
                print(match, f'匹配字段: {name},{standard_date}')

            # 将邮件标记为未读
            # mail.store(mail_ids[i], '-FLAGS', '\\Seen')

    # 退出
    mail.logout()

    return True, Info("爬取成功", reports)


def send_remind_email(date, report):
    status, _ = test_conn_email()
    if not status:
        return False, Info("邮箱源错误")

    _, info = get_config(id=2)
    email_user = info.data["configEmail"]
    password = info.data["configSecretKey"]

    subject = "日报未提交提醒"
    body = f"{date}日报没有提交，请及时补交。"
    to_emails = report

    if email_user.endswith('@qq.com'):
        smtp_server = 'smtp.qq.com'
    elif email_user.endswith('@163.com'):
        smtp_server = 'smtp.163.com'
    elif email_user.endswith('@sia.cn'):
        smtp_server = 'mail.cstnet.cn'
    else:
        print("不支持的邮箱类型，请检查邮箱地址")
        return False, Info("不支持的邮箱类型，请检查邮箱")

    smtp_port = 465  # SSL 端口
    smtp_user = email_user  # 发送邮件的邮箱
    smtp_password = password  # 授权码

    # 创建邮件对象
    msg = MIMEMultipart()
    msg['From'] = smtp_user
    msg['To'] = ", ".join(to_emails)  # 群发邮件邮箱的列表
    msg['Subject'] = subject

    # 添加邮件正文
    msg.attach(MIMEText(body, 'plain', 'utf-8'))

    # 手动打开和关闭连接
    smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)

    try:
        smtp.login(smtp_user, smtp_password)  # 登录
        smtp.sendmail(smtp_user, to_emails, msg.as_string())  # 发送邮件
        print("未提交提醒发送成功!")  # 确保在发送成功时打印
    except smtplib.SMTPException as e:
        print(f"SMTP error occurred: {e}")
    except Exception as e:
        print(f"Failed to send email: {e}")
    finally:
        smtp.quit()  # 确保在结束时关闭连接


def get_config(id):
    configuration = ConfigurationModel.query.get(id)  # 配置表中id为1的就是邮箱源
    if configuration is None:  # 去创建相关数据
        email = "example@email.com"
        secretkey = "example_secretkey"
        example = ConfigurationModel(id=id, email=email, secretkey=secretkey)
        db.session.add(example)
        db.session.commit()
        filter_data = {
            "configEmail": email,
            "configSecretKey": secretkey
        }
        return True, Info("新增了相关配置", filter_data)
    filter_data = {
        "configEmail": configuration.email,
        "configSecretKey": configuration.secretkey
    }
    return True, Info("配置获取成功", filter_data)


def update_config(id, email=None, secretkey=None):
    configuration = ConfigurationModel.query.get(id)
    if email:
        configuration.email = email
    if secretkey:
        configuration.secretkey = secretkey

    db.session.commit()
    filter_data = {
        "email": configuration.email,
        "secretKey": configuration.secretkey
    }

    return True, Info("配置修改成功", filter_data)


def test_conn_email():
    status1, info1 = get_config(id=1)  # 测试接收邮箱
    if not status1:
        return False, info1
    email1 = info1.data["configEmail"]
    secretkey1 = info1.data["configSecretKey"]

    status2, info2 = get_config(id=2)
    if not status2:
        return False, info2
    email2 = info2.data["configEmail"]
    secretkey2 = info2.data["configSecretKey"]

    try:
        # 创建 IMAP 服务器连接
        if email1.endswith('@qq.com'):
            mail = imaplib.IMAP4_SSL('imap.qq.com', 993)
        elif email1.endswith('@163.com'):
            mail = imaplib.IMAP4_SSL('imap.163.com', 993)
        elif email1.endswith('@sia.cn'):
            mail = imaplib.IMAP4_SSL('mail.cstnet.cn', 993)
        else:
            print("不支持的邮箱类型，请检查邮箱地址")
            return False, Info("不支持的邮箱类型，请检查邮箱地址")

        # 登录
        mail.login(email1, secretkey1)
    except Exception as e:
        print("源邮箱登录失败, 请检查配置邮箱和密钥")
        return False, Info("邮箱1登录失败, 请检查配置邮箱和密钥")

    try:
        # 创建 smtp 服务器连接
        if email2.endswith('@qq.com'):
            smtp_server = 'smtp.qq.com'
        elif email2.endswith('@163.com'):
            smtp_server = 'smtp.163.com'
        elif email2.endswith('@sia.cn'):
            smtp_server = 'mail.cstnet.cn'
        else:
            print("不支持的邮箱类型，请检查邮箱地址")
            return False, Info("不支持的邮箱类型，请检查邮箱")
        smtp_port = 465  # SSL 端口
        smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
        # 登录
        smtp.login(email2, secretkey2)
    except Exception as e:
        print("源邮箱登录失败, 请检查配置邮箱和密钥")
        return False, Info("邮箱2登录失败, 请检查配置邮箱和密钥")

    return True, Info("两个邮箱测试连接成功!")
